1 module unde.games.dizzy.omega.bug;
2 
3 import derelict.opengl3.gl;
4 
5 import std.conv;
6 import std.math;
7 import unde.games.object;
8 import unde.games.renderer;
9 import unde.games.collision_detector;
10 import unde.games.object;
11 import unde.games.dizzy.omega.main;
12 import unde.global_state;
13 
14 class Bug:StaticGameObject
15 {
16     static int num;
17     int number;
18 
19     bool killed;
20     bool sprayed;
21     
22     enum SPEED = 0.05;
23     enum G = 0.0025;
24     enum MAX_V = 0.05;
25     enum JUMP_V = 0.075;
26 
27     float def_x, def_y, def_z;
28     float dx = SPEED, dy = 0.0;
29     long frame;
30 
31     bool search_surface;
32     bool jump_mode;
33 
34     this(MainGameObject root, float[3] coords, string bug_solid, bool jump_mode = false)
35     {
36         def_x = x = coords[0];
37         def_y = y = coords[1];
38         def_z = z = coords[2];
39         number = num++;
40         models["bug"] = root.models["bug"];
41         collision_objects["solid"] = root.collision_objects[bug_solid];
42         this.jump_mode = jump_mode;
43         super(root);
44     }
45 
46     bool walk_anim(GlobalState gs, string name)
47     {
48         float f = (frame*4)%120;
49         float f2 = (frame*4)%240;
50         float degree = 0.0;
51         float translate = 0.0;
52         
53         if (f < 60.0)
54             translate = -0.1 + 0.2*f/60.0;
55         else if (f < 120.0)
56             translate = 0.1 - 0.2*(f - 60.0)/60.0;
57 
58         if (f2 < 120.0)
59             degree = f2/2 - 30.0;
60         else if (f2 < 240.0)
61             degree = 30.0 - (f2/2 - 60.0);
62         
63         if (name == "Bug-FL_Leg")
64         {
65             glTranslatef(0.5, 0.4, 0.0);
66             glRotatef(degree, 0.0, 0.0, 1.0);
67             glTranslatef(-0.5, -0.4, 0.0);
68         }
69         
70         if (name == "Bug-FR_Leg")
71         {
72             glTranslatef(0.5, 0.4, 0.0);
73             glRotatef(-degree, 0.0, 0.0, 1.0);
74             glTranslatef(-0.5, -0.4, 0.0);
75         }
76 
77         if (name == "Bug-BL_Leg")
78         {
79             glTranslatef(-0.5, 0.4, 0.0);
80             glRotatef(-degree, 0.0, 0.0, 1.0);
81             glTranslatef(0.5, -0.4, 0.0);
82         }
83 
84         if (name == "Bug-BR_Leg")
85         {
86             glTranslatef(-0.5, 0.4, 0.0);
87             glRotatef(degree, 0.0, 0.0, 1.0);
88             glTranslatef(0.5, -0.4, 0.0);
89         }
90         
91         if (name == "Bug-Head")
92         {
93             glTranslatef(0.8, 0.4, 0.0);
94             glRotatef(degree/2, 0.0, 1.0, 0.0);
95             glTranslatef(-0.8, -0.4, 0.0);
96         }
97 
98         return true;
99     }
100 
101     void kill()
102     {
103         killed = true;
104     }
105 
106     void spray()
107     {
108         sprayed = true;
109     }
110 
111     override void draw(GlobalState gs)
112     {
113         if (killed) return;
114         
115         glPushMatrix();
116         glTranslatef(x, y, z);
117         if (dx < 0) glRotatef(180,0,1,0);
118         recursive_render(gs, models["bug"], &walk_anim);
119         glPopMatrix();
120     }
121 
122     immutable float side_sensor_dx = 1.0;
123     immutable float[2] side_sensor_y = [0.5, 0.8];
124     
125     immutable float bottom_sensor_dx = 0.6;
126     immutable float bottom_sensor_dy = 0.5;
127 
128     override bool tick(GlobalState gs)
129     {
130         if (killed) return true;
131         
132         frame++;
133         x += dx;
134         y += dy;
135 
136         if (!jump_mode)
137         {
138             if (dx < 0 && (if_intersect (collision_objects["solid"], [x-side_sensor_dx, y+side_sensor_y[0], z-5*side_sensor_dx, x, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0))
139             {
140                 dx = SPEED;
141             }
142     
143             if (dx > 0 && (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-side_sensor_dx, x+5*side_sensor_dx, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0))
144             {
145                 dx = -SPEED;
146             }
147         }
148         
149         Intersect on_the_ground =
150             if_intersect (collision_objects["solid"], [x-bottom_sensor_dx, y, z-5*bottom_sensor_dx, x+bottom_sensor_dx, y+bottom_sensor_dy, z+5*bottom_sensor_dx]);
151 
152         if (jump_mode)
153         {
154             if (on_the_ground && (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-5*side_sensor_dx, x+2*side_sensor_dx, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0) ||
155                 abs(x - 475.6) < 0.25)
156             {
157                 dx = SPEED/2;
158                 dy = JUMP_V;
159                 search_surface = false;
160             }
161         }
162 
163         if (dy > -MAX_V)
164         {
165             dy -= G;
166         }
167 
168         if (search_surface && on_the_ground == 0)
169         {
170             if (jump_mode) dx = SPEED;
171             dy = 0;
172             search_surface = false;
173         }
174         
175         if (on_the_ground > 0 && (dy <= 0 || search_surface))
176         {
177             if (if_intersect (collision_objects["solid"], [x-bottom_sensor_dx, y+SPEED, z-5*bottom_sensor_dx, x+bottom_sensor_dx, y+SPEED+bottom_sensor_dy, z+5*bottom_sensor_dx]) > 0)
178             {
179                 search_surface = true;
180                 dy = SPEED;
181             }
182             else if (on_the_ground > 0) dy = 0;
183         }
184 
185         DizzyOmega dz = cast(DizzyOmega) root;
186         
187         if (!dz.stone1.inventory && abs(dz.stone1.x - 242.6) < 0.1 && abs(dz.stone1.y + 4.4) < 0.1 ||
188                 !dz.stone2.inventory && abs(dz.stone2.x - 242.6) < 0.1 && abs(dz.stone2.y + 4.4) < 0.1)
189         {
190             if (abs(x - 242.6) > 1.5 && abs((x+dx) - 242.6) < 1.5)
191             {
192                 dx = -dx;
193             }
194         }
195         else if (!dz.stone1.inventory && abs(dz.stone1.x - 242.6) < 0.1 && abs(dz.stone1.y + 5.2) < 0.1 ||
196                 !dz.stone2.inventory && abs(dz.stone2.x - 242.6) < 0.1 && abs(dz.stone2.y + 5.2) < 0.1)
197         {
198             if ( abs(x - 242.6) > 1.5 && abs((x+dx) - 242.6) < 1.5 )
199             {
200                 dy = JUMP_V;
201                 search_surface = false;
202             }
203         }
204 
205         return true;
206     }    
207 
208     override void load(string[string] s)
209     {
210         string p = "bug"~number.to!(string);
211         if (p~"-x" in s)
212             x = s[p~"-x"].to!(float);
213         else
214             x = def_x;
215             
216         if (p~"-y" in s)
217             y = s[p~"-y"].to!(float);
218         else
219             y = def_y;
220             
221         if (p~"-z" in s)
222             z = s[p~"-z"].to!(float);
223         else
224             z = def_z;
225 
226         if (p~"-dx" in s)
227             dx = s[p~"-dx"].to!(float);
228         else
229             dx = SPEED;
230 
231         if (p~"-dy" in s)
232             dy = s[p~"-dy"].to!(float);
233         else
234             dy = 0.0;
235 
236         if (p in s)
237         {
238             killed = (s[p] == "killed");
239         }
240         else
241             killed = false;
242 
243         if (p~"-s" in s)
244         {
245             sprayed = (s[p~"-s"] == "sprayed");
246         }
247         else
248             sprayed = false;
249     }
250 
251     override void save(ref string[string] s)
252     {
253         string p = "bug"~number.to!(string);
254         if (killed)
255             s[p] = "killed";
256 
257         if (sprayed)
258             s[p~"-s"] = "sprayed";
259 
260         s[p~"-x"] = x.to!(string);
261         s[p~"-y"] = y.to!(string);
262         s[p~"-z"] = z.to!(string);
263         s[p~"-dx"] = dx.to!(string);
264         s[p~"-dy"] = dy.to!(string);
265     }    
266 }